using System;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Criterion;
using SIP.PN.DAO.Interfaces;
using SIP.PN.Filtros.Interfaces;

namespace SIP.PN.DAO
{
    public abstract class HibernateDao<TEntity, TId> : IDao
    {
        private ISessionFactory sessionFactory;

        public ISessionFactory SessionFactory
        {
            set { sessionFactory = value; }
        }

        protected virtual ISession Session
        {
            get
            {
                return sessionFactory.GetCurrentSession();
            }
        }

        public virtual TEntity Obtener(TId Id)
        {
            return Session.Get<TEntity>(Id);
        }

        public virtual void Guardar(TEntity entity)
        {
            //Session.Persist(entity);
            Session.SaveOrUpdate(entity);
        }

        public virtual void Eliminar(TEntity entity)
        {
            Session.Delete(entity);
        }
    }

    public abstract class HibernateDao<TEntity, TId, TFilter> : HibernateDao<TEntity, TId> where TFilter : class, IFiltro
    {
        public virtual IList<TEntity> Listar(TFilter filtro)
        {
            ICriteria criteria = Session.CreateCriteria(typeof(TEntity));
            if (filtro != null)
            {
                criteria.SetFirstResult(filtro.Desde.GetValueOrDefault(0));
                filtro.AgregarFiltros(criteria);
                if (filtro.Cantidad.HasValue)
                    criteria.SetMaxResults(filtro.Cantidad.Value);

                if (filtro.Ordenes != null)
                    if (filtro.Ordenes.Count > 0)
                        foreach (Order order in filtro.Ordenes)
                        {
                            criteria.AddOrder(order);
                           }
            }

            return criteria.List<TEntity>();
        }

        public int ObtenerCantidadRegistros(TFilter filtro)
        {
            ICriteria criteria = Session.CreateCriteria(typeof(TEntity));
            filtro.AgregarFiltros(criteria);
            criteria.SetProjection(Projections.RowCount());
            object data = criteria.UniqueResult();
            return Convert.ToInt32(data);
        }
    }
}
